//***********************************************************************
//	File:		Game.cpp
//	Author:		
//	Course:		SGP 1405
//	Purpose:	Game class will run game logic
//***********************************************************************
//***********************************************************************
//	Purposfully left blank for all comments regarding this file 
//	
//	
//	
//***********************************************************************
#pragma once
#define WIN32_LEAN_AND_MEAN 
#include <ctime>
#include <Windows.h>

#include "Game.h"
#include "../GameStates/MainMenu.h"
#include "../GameStates/LoadGame.h"

#include "../SGD Wrappers/SGD_AudioManager.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"
#include "../SGD Wrappers/SGD_InputManager.h"
#include "../SGD Wrappers/SGD_String.h"

#include "Game.h"
#include "../TileSystem/TileSystem.h"
#include "../ParticleSystem/ParticleSystem.h"
#include "../SGD Wrappers/SGD_GraphicsManager.h"

#include "../TinyXML/tinyxml.h"

// Static instance variable 
Game* Game::s_pInstance = nullptr;

// Getting dat Instance - will return if one already exists
Game* Game::GetInstance ( void )
{
	if ( s_pInstance == nullptr )
	{
		s_pInstance = new Game;
	}

	return s_pInstance;
};

// Deletes dat Instance
void Game::DeleteInstance ( void )
{
	delete s_pInstance;
	s_pInstance = nullptr;
}

// Initalizes the game, takes in width and height from WinMain
// All Images, Sounds, and variables will be loaded here
bool Game::Initialize ( float screenWidth , float screenHeight )
{
	// Seed for the start of the game
	srand((unsigned int)time(nullptr));
	rand(); 

	// Bring in the size parameter
	m_fScreenWidth = screenWidth; 
	m_fScreenHeight = screenHeight; 

	//Store the SGD singletons
	m_pAudio = SGD::AudioManager::GetInstance(); 
	m_pGraphics = SGD::GraphicsManager::GetInstance(); 
	m_pInput = SGD::InputManager::GetInstance(); 

	// did the singletons work?
	if (m_pAudio->Initialize() == false
		|| m_pGraphics->Initialize(false) == false
		|| m_pInput->Initialize() == false)
	{
		return false; 
	}


	//Load in all textures
	m_hPlayerImg = m_pGraphics->LoadTexture("resource/graphics/player1.png", { 255, 0, 255});
	m_hPlayerAirImg = m_pGraphics->LoadTexture("resource/graphics/Player2Reticle.png", { 255, 255, 255 }); 
	m_hBulletImg = m_pGraphics->LoadTexture("resource/graphics/SGD_Bullet.png", { 255, 255, 255 }); 
	m_hAnklebiterImg = m_pGraphics->LoadTexture("resource/graphics/DemonBrain.png");
	//m_hBasherImg = m_pGraphics->LoadTexture("resource/graphics/Human_Beserker.png");


	//Load in all audio
	m_hBackgroundMus = m_pAudio->LoadAudio("resource/Audio/SH_LegendofZelda-NES-DungeonTheme.xwm"); 
	m_hSampleSfx = m_pAudio->LoadAudio("resource/Audio/SH_LOZ_Die.wav"); 
	m_hSniperBulletSfx = m_pAudio->LoadAudio("resource/Audio/SniperBulletSfx.wav"); 


	//Allocate & initialize the font
	m_pFont = new BitmapFont; 
	// Initialize the bitmap font here
	m_pFont->Initialize("resource/data/BBBitmapFont.xml",
		"resource/Visual/BBBitmapFont_0.png"); 


	int nMasterVolume = 0; 
	int nSfxVolume = 0; 
	int fullScreen = 0; 

	// Loading up saved options
	// Create the doc
	TiXmlDocument doc;

	if (doc.LoadFile("resource/data/SavedOptions.xml") == true)
	{
		TiXmlElement* pRoot = doc.RootElement();

		TiXmlElement* pMasterVolume = pRoot->FirstChildElement("MasterVolume");
		pMasterVolume->Attribute("MasterVolume", &nMasterVolume);

		TiXmlElement* pSoundFx = pRoot->FirstChildElement("SFXVolume"); 
		pSoundFx->Attribute("SfxVolume", &nSfxVolume); 

		TiXmlElement* pFullscreen = pRoot->FirstChildElement("Fullscreen"); 
		pFullscreen->Attribute("Fullscreen", &fullScreen); 
	}

	SGD::AudioManager::GetInstance()->SetMasterVolume(SGD::AudioGroup::Music, nMasterVolume); 
	SGD::AudioManager::GetInstance()->SetMasterVolume(SGD::AudioGroup::SoundEffects, nSfxVolume);

	if(fullScreen == 0)
		m_bFullScreen = false;
	else
		m_bFullScreen = true;


	// go to the main menu state
	ChangeState(MainMenu::GetInstance());

	m_ulGameTime = GetTickCount(); 

	return true; 
};

// If everything is good we return 0 to keep going
int Game::Update ( void )
{
	// Has the whole world come crashing down around you?
	if (m_pAudio->Update() == false
		|| m_pGraphics->Update() == false
		|| m_pInput->Update() == false)
	{
		return -1337;  //crashing hard
	}
	
	unsigned long currTime = GetTickCount(); 
	float dt = (currTime - m_ulGameTime) / 1000.0f; 
	m_ulGameTime = currTime; 

	if (dt > 0.125f)
	{
		dt = 0.125f; 
	}

	if (m_pInput->IsKeyDown(SGD::Key::Alt) && m_pInput->IsKeyPressed(SGD::Key::Enter))
	{
		if (m_bFullScreen)
		{
			m_pGraphics->Resize({ 800, 600 }, false);
		}
		else
		{
			m_pGraphics->Resize({ 800, 600 }, true);
		}
		m_bFullScreen = !m_bFullScreen;
		return 0;
	}

	if (m_pInput->IsKeyDown(SGD::Key::Alt) && m_pInput->IsKeyPressed(SGD::Key::Tab))
	{
		// put in Alt-Tab functionality here
		m_bIsPaused = true; 
	}
	
		
	

	if (m_pCurrState->Input() == false)
		return 1; //successful exit


	// Update and Render Current state
	if (m_bIsPaused == false)
	{
		m_pCurrState->Update(dt);
	}
	m_pCurrState->Render(); 

	return 0; // Keep Playing 


}; 

// All Images, Sounds, and variables will be unloaded here
void Game::Terminate(void)
{
	// Get out of whatever state we are in
	ChangeState(nullptr);

	// Delete all of the states

	// Terminate and delete the font
	m_pFont->Terminate(); 
	delete m_pFont; 
	m_pFont = nullptr; 

	// unload all of the graphics
	m_pGraphics->UnloadTexture(m_hPlayerImg); 
	m_pGraphics->UnloadTexture(m_hPlayerAirImg);
	m_pGraphics->UnloadTexture(m_hBulletImg); 
	m_pGraphics->UnloadTexture(m_hAnklebiterImg);

	//unload all of the audio
	m_pAudio->UnloadAudio(m_hBackgroundMus); 
	m_pAudio->UnloadAudio(m_hSampleSfx); 
	m_pAudio->UnloadAudio(m_hSniperBulletSfx);

	// Terminate and deallocate the SGD Wrappers
	m_pAudio->Terminate();
	m_pAudio = nullptr;
	SGD::AudioManager::DeleteInstance();

	m_pGraphics->Terminate();
	m_pGraphics = nullptr;
	SGD::GraphicsManager::DeleteInstance();

	m_pInput->Terminate();
	m_pInput = nullptr;
	SGD::InputManager::DeleteInstance();
};


/**************************************************************/
// ChangeState
//	- exit the current state to release resources
//	- enter the new state to allocate resources
//	- DANGER! Exiting the current state can CRASH the program!
//	  The state can ONLY be exited from the
//	  Input, Update, and Render methods!!!
void Game::ChangeState(IGameState* pNewState)
{
	// Exit the old state
	if (m_pCurrState != nullptr)
		m_pCurrState->Exit();
	

	// Store the new state
	m_pCurrState = pNewState;

	// Enter the new state
	if (m_pCurrState != nullptr)
		m_pCurrState->Enter();
}

SGD::HTexture Game::GetImage( int type ) const
{
	switch ( type )
	{
	case ANKLEBITER:
	{
		return m_hAnklebiterImg;
	}
		break;

	default:
		return SGD::INVALID_HANDLE;
		break;
	}
}